/* File to test task switching with alarms */

#include <tr_port.h>
#include <tiros/tr_time.h>
#include "proj_config.h"
#include "util.h"




#define NUM_TASKS  5
#define TSK_STKSIZE	(TRPORT_MIN_CTXT_SZ + 64)
osword_t task_stk[NUM_TASKS][TSK_STKSIZE];
osword_t*    task_stk_ptr[NUM_TASKS];

volatile int curr_task = 0;


trtime_t  curr_time;
trtime_t  alarm_interval;

uint8_t osint_alarm_reached(const trtime_t * t )
{

	putstring("Timer reached\n");
	hal_time_get(&curr_time);
	time_add(&curr_time, &alarm_interval, &curr_time);
	
	hal_alarm_set(&curr_time);

	return 1;
}


osword_t* osint_taskswitcher(osword_t *oldstkptr)
{
	task_stk_ptr[curr_task] = oldstkptr;
	curr_task++;
	if (curr_task == NUM_TASKS)
		curr_task = 0;
	putstring("Switching: "); puthexchar(curr_task); putchar('\n');
	return  task_stk_ptr[curr_task];
}

osword_t* osint_running_task_ctxt(void)
{
	return task_stk_ptr[curr_task];
}

void task(void * dummy)
{
	int myid = (int)(dummy);

	while (1) {                         //main loop, never ends...
		putstring("Hello World from task : ");
		puthexchar((unsigned char) myid);
		putchar('\n');

		if (myid == 0)
			hal_ctxt_switch();
		else
			delayms(2000);

	}
}

/** other task is different, in that it explicitly performs a context
 *  switch */
void other_task(void * dummy)
{
	int myid = (int)(dummy);

	while (1) {                         //main loop, never ends...
		putstring("Hello World from other_task : ");
		puthexchar((unsigned char) myid);
		putchar('\n');

		delayms(1000);
		hal_ctxt_switch();

	}
}



/* Implement in platform_xxx.c . To do any extra initialization, such
 * as serial port setup */
void platform_init(void);

int main(void) 
{
	int i;

	platform_init();
	hal_init();


	for (i=0; i< NUM_TASKS-1; i++) {
		task_stk_ptr[i] = hal_stk_init(task_stk[i],
					       TSK_STKSIZE, 
					       task,
					       (osptr_t)i);
	}

	/* This task performs an explicit context switch */
	task_stk_ptr[i] = hal_stk_init(task_stk[i],
				       TSK_STKSIZE, 
				       other_task,
				       (osptr_t)i);


	alarm_interval.units  = 2;
	alarm_interval.subunits    = 0;

	hal_time_get(&curr_time);
	time_add(&curr_time, &alarm_interval, &curr_time);
	
	hal_alarm_set(&curr_time);


	hal_ctxt_load( task_stk_ptr[0]);

	putstring("Main: Should not reach here\n");
	return 0;
}

